package cn.iocoder.yudao.module.product.spu.service;

import cn.iocoder.yudao.framework.business.basic.pojo.dto.LocationQueryDTO;
import cn.iocoder.yudao.framework.business.basic.pojo.dto.SortQueryDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.spu.dal.dataobject.ProductSpuDO;
import cn.iocoder.yudao.module.product.spu.vo.*;
import io.micrometer.common.lang.Nullable;
import jakarta.validation.Valid;
import org.springframework.scheduling.annotation.Async;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 产品 SPU Service 实现类
 *
 * @author 芋道源码
 */
public interface ProductSpuService {

    /**
     * 创建产品 SPU
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createSpu(@Valid ProductSpuSaveReqVO createReqVO);

    /**
     * 更新产品 SPU
     *
     * @param updateReqVO 更新信息
     */
    void updateSpu(@Valid ProductSpuSaveReqVO updateReqVO);

    /**
     * 删除产品 SPU
     *
     * @param id 编号
     */
    void deleteSpu(Long id);

    /**
     * 创建产品 SPU
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createSpu(@Valid AppProductSpuSaveReqVO createReqVO);

    /**
     * 更新产品 SPU
     *
     * @param updateReqVO 更新信息
     */
    void updateSpu(@Valid AppProductSpuSaveReqVO updateReqVO);

    /**
     * 获得产品 SPU
     *
     * @param id 编号
     * @return 产品 SPU
     */
    ProductSpuDO getSpu(Long id);

    /**
     * 获得商品 SPU
     *
     * @param id 编号
     * @param includeDeleted 是否包含已删除的
     * @return 商品 SPU
     */
    ProductSpuDO getSpu(Long id, boolean includeDeleted);

    /**
     * 浏览产品 SPU
     *
     * @param userId 用户编号
     * @param id     编号
     * @return 产品 SPU
     */
    AppProductSpuDetailRespVO browseSpu(Long userId, Long id);

    /**
     * 商家产品 SPU
     *
     * @param id 编号
     * @return 产品 SPU
     */
    AppShopProductSpuDetailRespVO shopSpu(Long id);

    /**
     * 获得产品 SPU 列表
     *
     * @param ids 编号数组
     * @return 产品 SPU 列表
     */
    List<ProductSpuDO> getSpuList(Collection<Long> ids);

    /**
     * 获得产品 SPU Map
     *
     * @param ids 编号数组
     * @return 产品 SPU Map
     */
    default Map<Long, ProductSpuDO> getSpuMap(Collection<Long> ids) {
        List<ProductSpuDO> list = getSpuList(ids);
        return CollectionUtils.convertMap(list, ProductSpuDO::getId);
    }

    /**
     * 获得指定状态的产品 SPU 列表
     *
     * @param status 状态
     * @return 产品 SPU 列表
     */
    List<ProductSpuDO> getSpuListByStatus(Integer status);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品spu分页
     */
    PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品 SPU 分页
     */
    PageResult<AppProductSpuRespVO> getSpuPage(AppProductSpuPageReqVO pageReqVO);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品 SPU 分页
     */
    PageResult<AppProductSpuRespVO> getSpuPageByPlatformCategoryId(AppProductSpuPageForPlatformCategoryReqVO pageReqVO);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品 SPU 分页
     */
    PageResult<AppProductSpuRespVO> getSpuPageByProductCategoryId(AppProductSpuPageForProductCategoryReqVO pageReqVO);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品 SPU 分页
     */
    PageResult<AppProductSpuRespVO> getSpuPageByCloudAlliance(AppProductSpuPageForCloudAllianceReqVO pageReqVO);

    /**
     * 获得产品 SPU 分页
     *
     * @param pageReqVO 分页查询
     * @return 产品 SPU 分页
     */
    PageResult<AppProductSpuRespVO> getSpuPageByDishAttribute(@Valid AppProductSpuPageForDishAttributeReqVO pageReqVO);

    /**
     * 更新产品 SPU 库存（增量）
     *
     * @param stockIncCounts SPU 编号与库存变化（增量）的映射
     */
    void updateSpuStock(Map<Long, Integer> stockIncCounts);

    /**
     * 更新产品 SPU 销量（增量）
     *
     * @param salesCountIncCounts SPU 编号与销量变化（增量）的映射
     */
    void updateSpuSalesCount(Map<Long, Integer> salesCountIncCounts);

    /**
     * 更新 SPU 状态
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO);

    /**
     * 更新 SPU 状态
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuStatus(AppProductSpuUpdateStatusReqVO updateReqVO);

    /**
     * 更新 SPU 推荐类型
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuRecommend(ProductSpuUpdateRecommendReqVO updateReqVO);

    /**
     * 更新 SPU 推荐类型及排序
     *
     * @param updateReqVO 更新请求
     */
    void updateRecommendSort(ProductSpuUpdateRecommendSortReqVO updateReqVO);

    /**
     * 更新 SPU 置顶
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuSticky(ProductSpuUpdateStickyReqVO updateReqVO);

    /**
     * 更新 SPU 推荐类型
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuRecommend(AppProductSpuUpdateRecommendReqVO updateReqVO);

    /**
     * 更新 SPU 是否积分产品
     *
     * @param updateReqVO 更新请求
     */
    void updateSpuIntegral(AppProductSpuUpdateIntegralReqVO updateReqVO);

    /**
     * 获取 SPU 列表标签对应的 Count 数量
     *
     * @param type 产品类型：mall-商城、food-美食、hotel-酒店……
     * @return Count 数量
     */
    Map<String, Long> getSpuCount(@Nullable Long shopId, String type);

    /**
     * 通过分类 categoryId 查询 SPU 个数
     *
     * @param categoryId 分类 categoryId
     * @return SPU 数量
     */
    Long getSpuCountByCategoryId(Long categoryId);


    /**
     * 校验产品是否有效。如下情况，视为无效：
     * 1. 产品编号不存在
     * 2. 产品被禁用
     *
     * @param ids 产品编号数组
     * @return 产品 SPU 列表
     */
    List<ProductSpuDO> validateSpuList(Collection<Long> ids);

    /**
     * 更新产品 SPU 浏览量
     *
     * @param id       产品 SPU 编号
     * @param incCount 增加的数量
     */
    @Async
    void updateBrowseCount(Long id, int incCount);

    /**
     * 计算折扣价
     *
     * @param discountPercent 折扣
     * @param price  原价
     * @return 折扣价
     */
    Integer calculateMemberLevelPrice(Integer discountPercent, Integer price);

    /**
     * 获得产品 SPU 总数
     *
     * @return 产品 SPU 总数
     */
    Long getProductCountByShopId(Long shopId);

    /**
     * 批量查询 SPU 数量 MAP
     *
     * @param shopIds 店铺编号列表
     * @return SPU 数量 MAP
     */
    Map<Long, Integer> getSpuCountMapByShopIds(Collection<Long> shopIds);

    /**
     * 根据指定行业类目编号获取有产品的店铺编号及距离
     *
     * @param pcIds 行业类目编号集合
     * @param location 经纬度
     * @param sort 排序
     * @return 店铺编号集合
     */
    Map<Long, Integer> getShopDistanceMapByPlatformCategoryIds(Set<Long> pcIds, LocationQueryDTO location, SortQueryDTO sort);

}
